#ifndef _OBJARRAY_H_CSEAPI_
#define _OBJARRAY_H_CSEAPI_

// const of CSE Data Type
#define dtInt                      0
#define dtWint                     1
#define dtFloat                    2
#define dtStr                      3
#define dtTier                     4
#define dtBuff                     5
#define dtDict                     6
#define dtInstance                 7
#define dtId                       8
#define dtStrong                   9
#define dtWeak                     10
#define dtNull                     11
#define dtNotator                  16

typedef union CSEOBJ *CseObj;

typedef struct {
    TUint32 hash;
    CseObj key;
    CseObj value;
} TEntryPoint, *PEntryPoint;

union CSEOBJ {
    struct {
        CseObj vValue;
        CseObj bHold;
    };

    struct {
        TInt iValue;
        union {
            TInt iFlag;    // flag for int, weak, strong
            struct {
                TUint8 b1;
                TUint8 b2;
                TUint8 b3;
                TUint8 b4;
            } bFlag;
            struct {
                TUint16 h1;
                TUint16 h2;
            } hFlag;
        };
    };

    TWint wValue;
    TDouble fValue;

    struct {
        TXchar *sValue;
        TUint32 hash;
    };

    struct {
        TInt *tValue;
        TInt32 iFix;  // fix size for str, tier, buff, dict
    };

    CseObj *bValue;
    PEntryPoint entry;
};

typedef struct
{
    TUint32 mask;
    TUint32 FilledCount;
    CseObj binded;
    TUint32 count;
} CSE_DICT_EXT;

typedef struct
{
    TUint32 RefCount;
    union {
        TInt32 flags;
        TInt8 DataType;
        
        struct {
            TInt8 b1;
            TInt8 b2;
            TInt8 b3;
            TInt8 b4;
        } bFlag;

        struct {
            TInt16 h1;
            TInt16 h2;
        } hFlag;
    };
    union CSEOBJ context;
} CSE_BASE_TYPE;

extern CSE_IMPEXP_IN CseObj dummy;

class TCseObj;     // forward declare

class CSE_IMPEXP_IN TObjArray
{
private:
    TBool copyFrom(const CseObj* pSour, int iLen, int iOff, TBool RefInc) const;
    TObjArray& joinEx(const CseObj *pSour, int iSourLen);
    void insertEx(int iPos, const CseObj *pSour, int iLen);

protected:
    CseObj *m_data;

public:
    TObjArray();
    TObjArray(int MagicNum, TObjArray& bArray);

    TObjArray(const TObjArray& bArray);
    TObjArray(int count);
    TObjArray(const CseObj* pSour, int n, int iExt=0);
    ~TObjArray();

    TObjArray& join(const TObjArray& bArray, int index=0);
    TObjArray& join(const CseObj *pSour, int iSourLen);

    TObjArray& operator=(const TObjArray& bArray);

    void operator+=(const TObjArray& bArray);
    void operator+=(const TCseObj& obj);

    static TObjArray format(int ArgNum, ...);
    TObjArray multi(int n) const;
    
    TCseObj& sub(int index) const;         // same to operator[]
    TCseObj& operator[](int index) const;

    CseObj *addr() const;
    int len() const;
    TBool isEmpty() const;
    TInt compare(const TObjArray& other) const;
    
    TObjArray slice(int index, int iLen=-1) const;

    CseObj *transfer(CseObj *other);
    void exchange(TObjArray& other);
    const TCseObj& append(const TCseObj& obj);
    TObjArray& add(const TCseObj& obj, int *pIndex=NULL);
    const TCseObj& insert(int index, const TCseObj& obj);
    void remove(int index, int iLen=1);
    TCseObj pop(int index=-1);

    void clear();
    int truncate(int iLen) const;
    int sortAdd(const TCseObj& obj);
    void sort() const;

    int find(const TCseObj& vSub, int from=0) const;
    void resize(int iSize);
    TCharArray str() const;
    
    TBool enumItem(void*& pIter, TCseObj *pRet=NULL) const;
};

extern CSE_IMPEXP_IN const TObjArray& CseEmptyBuff;

extern CSE_IMPEXP_IN TBool operator==(const TObjArray& x, const TObjArray& y);
extern CSE_IMPEXP_IN TBool operator!=(const TObjArray& x, const TObjArray& y);
extern CSE_IMPEXP_IN TBool operator>(const TObjArray& x, const TObjArray& y);
extern CSE_IMPEXP_IN TBool operator>=(const TObjArray& x, const TObjArray& y);
extern CSE_IMPEXP_IN TBool operator<(const TObjArray& x, const TObjArray& y);
extern CSE_IMPEXP_IN TBool operator<=(const TObjArray& x, const TObjArray& y);

#endif
